"""ChromaDB缓存服务 - 使用Redis缓存ChromaDB查询结果"""

import hashlib
import json
import logging
from typing import Dict, List, Any, Optional
from datetime import datetime, timedelta

from app.configs.redis_config import redis_manager
from app.services.chroma_service import ChromaService

logger = logging.getLogger(__name__)


class ChromaCacheService:
    """ChromaDB缓存服务"""
    
    def __init__(self):
        self.chroma_service = ChromaService()
        self.redis = redis_manager
        
        # 缓存配置
        self.cache_config = {
            "knowledge_search": {
                "expire": 3600,  # 知识检索缓存1小时
                "prefix": "chroma:knowledge:"
            },
            "conversation_search": {
                "expire": 1800,  # 对话搜索缓存30分钟
                "prefix": "chroma:conversation:"
            },
            "message_search": {
                "expire": 900,   # 消息搜索缓存15分钟
                "prefix": "chroma:message:"
            },
            "similarity_search": {
                "expire": 1800,  # 相似性搜索缓存30分钟
                "prefix": "chroma:similarity:"
            }
        }
    
    def _generate_cache_key(self, prefix: str, query_params: Dict[str, Any]) -> str:
        """生成缓存键"""
        # 将查询参数序列化并生成哈希
        params_str = json.dumps(query_params, sort_keys=True, ensure_ascii=False)
        params_hash = hashlib.md5(params_str.encode('utf-8')).hexdigest()
        return f"{prefix}{params_hash}"
    
    def _is_cache_enabled(self) -> bool:
        """检查缓存是否启用"""
        return self.redis.is_available()
    
    async def search_knowledge_with_cache(self, query: str, n_results: int = 5, 
                                        filters: Optional[Dict] = None) -> Dict[str, Any]:
        """带缓存的知识检索"""
        cache_config = self.cache_config["knowledge_search"]
        
        # 生成缓存键
        query_params = {
            "query": query,
            "n_results": n_results,
            "filters": filters or {}
        }
        cache_key = self._generate_cache_key(cache_config["prefix"], query_params)
        
        # 尝试从缓存获取
        if self._is_cache_enabled():
            cached_result = self.redis.get(cache_key)
            if cached_result:
                logger.info(f"🎯 [ChromaCache] 知识检索缓存命中: {query[:50]}...")
                return {
                    "results": cached_result,
                    "from_cache": True,
                    "cache_key": cache_key
                }
        
        # 缓存未命中，查询ChromaDB
        logger.info(f"🔍 [ChromaCache] 知识检索缓存未命中，查询ChromaDB: {query[:50]}...")
        
        try:
            # 调用ChromaDB服务
            results = await self.chroma_service.search_knowledge(
                query=query,
                n_results=n_results,
                filters=filters
            )
            
            # 存储到缓存
            if self._is_cache_enabled() and results:
                self.redis.set(cache_key, results, expire=cache_config["expire"])
                logger.info(f"💾 [ChromaCache] 知识检索结果已缓存: {cache_key}")
            
            return {
                "results": results,
                "from_cache": False,
                "cache_key": cache_key
            }
            
        except Exception as e:
            logger.error(f"❌ [ChromaCache] 知识检索失败: {e}")
            return {
                "results": None,
                "from_cache": False,
                "error": str(e)
            }
    
    async def search_conversations_with_cache(self, user_id: str, query: str = "", 
                                            n_results: int = 10) -> Dict[str, Any]:
        """带缓存的对话搜索"""
        cache_config = self.cache_config["conversation_search"]
        
        # 生成缓存键
        query_params = {
            "user_id": user_id,
            "query": query,
            "n_results": n_results
        }
        cache_key = self._generate_cache_key(cache_config["prefix"], query_params)
        
        # 尝试从缓存获取
        if self._is_cache_enabled():
            cached_result = self.redis.get(cache_key)
            if cached_result:
                logger.info(f"🎯 [ChromaCache] 对话搜索缓存命中: {user_id}")
                return {
                    "results": cached_result,
                    "from_cache": True,
                    "cache_key": cache_key
                }
        
        # 缓存未命中，查询ChromaDB
        logger.info(f"🔍 [ChromaCache] 对话搜索缓存未命中，查询ChromaDB: {user_id}")
        
        try:
            # 调用ChromaDB服务
            results = await self.chroma_service.search_conversations(
                user_id=user_id,
                query=query,
                n_results=n_results
            )
            
            # 存储到缓存
            if self._is_cache_enabled() and results:
                self.redis.set(cache_key, results, expire=cache_config["expire"])
                logger.info(f"💾 [ChromaCache] 对话搜索结果已缓存: {cache_key}")
            
            return {
                "results": results,
                "from_cache": False,
                "cache_key": cache_key
            }
            
        except Exception as e:
            logger.error(f"❌ [ChromaCache] 对话搜索失败: {e}")
            return {
                "results": None,
                "from_cache": False,
                "error": str(e)
            }
    
    async def similarity_search_with_cache(self, query_text: str, collection_name: str = None,
                                         n_results: int = 5, filters: Optional[Dict] = None) -> Dict[str, Any]:
        """带缓存的相似性搜索"""
        cache_config = self.cache_config["similarity_search"]
        
        # 生成缓存键
        query_params = {
            "query_text": query_text,
            "collection_name": collection_name or "default",
            "n_results": n_results,
            "filters": filters or {}
        }
        cache_key = self._generate_cache_key(cache_config["prefix"], query_params)
        
        # 尝试从缓存获取
        if self._is_cache_enabled():
            cached_result = self.redis.get(cache_key)
            if cached_result:
                logger.info(f"🎯 [ChromaCache] 相似性搜索缓存命中: {query_text[:50]}...")
                return {
                    "results": cached_result,
                    "from_cache": True,
                    "cache_key": cache_key
                }
        
        # 缓存未命中，查询ChromaDB
        logger.info(f"🔍 [ChromaCache] 相似性搜索缓存未命中，查询ChromaDB: {query_text[:50]}...")
        
        try:
            # 调用ChromaDB服务
            results = await self.chroma_service.similarity_search(
                query_text=query_text,
                collection_name=collection_name,
                n_results=n_results,
                filters=filters
            )
            
            # 存储到缓存
            if self._is_cache_enabled() and results:
                self.redis.set(cache_key, results, expire=cache_config["expire"])
                logger.info(f"💾 [ChromaCache] 相似性搜索结果已缓存: {cache_key}")
            
            return {
                "results": results,
                "from_cache": False,
                "cache_key": cache_key
            }
            
        except Exception as e:
            logger.error(f"❌ [ChromaCache] 相似性搜索失败: {e}")
            return {
                "results": None,
                "from_cache": False,
                "error": str(e)
            }
    
    def invalidate_user_cache(self, user_id: str) -> bool:
        """清除用户相关的缓存"""
        if not self._is_cache_enabled():
            return False
        
        try:
            # 获取所有相关的缓存键
            patterns = [
                f"chroma:conversation:*{user_id}*",
                f"chroma:message:*{user_id}*"
            ]
            
            deleted_count = 0
            for pattern in patterns:
                keys = self.redis.keys(pattern)
                for key in keys:
                    if self.redis.delete(key):
                        deleted_count += 1
            
            logger.info(f"🧹 [ChromaCache] 已清除用户 {user_id} 的 {deleted_count} 个缓存")
            return True
            
        except Exception as e:
            logger.error(f"❌ [ChromaCache] 清除用户缓存失败 {user_id}: {e}")
            return False
    
    def invalidate_knowledge_cache(self) -> bool:
        """清除知识检索缓存"""
        if not self._is_cache_enabled():
            return False
        
        try:
            keys = self.redis.keys("chroma:knowledge:*")
            deleted_count = 0
            for key in keys:
                if self.redis.delete(key):
                    deleted_count += 1
            
            logger.info(f"🧹 [ChromaCache] 已清除 {deleted_count} 个知识检索缓存")
            return True
            
        except Exception as e:
            logger.error(f"❌ [ChromaCache] 清除知识缓存失败: {e}")
            return False
    
    def get_cache_stats(self) -> Dict[str, Any]:
        """获取缓存统计信息"""
        if not self._is_cache_enabled():
            return {"status": "disabled"}
        
        try:
            stats = {}
            for cache_type, config in self.cache_config.items():
                keys = self.redis.keys(f"{config['prefix']}*")
                stats[cache_type] = {
                    "count": len(keys),
                    "prefix": config["prefix"],
                    "expire": config["expire"]
                }
            
            # Redis整体信息
            redis_info = self.redis.get_info()
            stats["redis_info"] = redis_info
            
            return stats
            
        except Exception as e:
            logger.error(f"❌ [ChromaCache] 获取缓存统计失败: {e}")
            return {"status": "error", "error": str(e)}


# 创建全局缓存服务实例
chroma_cache_service = ChromaCacheService()
